package com.soccertgc.core.game
{
	
	import com.soccertgc.core.DispatcherDataObject;
	import com.soccertgc.core.Position;
	import com.soccertgc.utils.DateUtils;
	import com.soccertgc.utils.StringUtils;
	
	import flash.events.Event;
	import flash.utils.Dictionary;
	

	public class GameTeam extends DispatcherDataObject
	{
	
		// -------------------------------------------------------------------------------
		// CONSTANTS
		// -------------------------------------------------------------------------------
		
		// JSON data property names
		protected static const		JSON_PROPERTY_NAME:String                  	= "name";
		protected static const		JSON_PROPERTY_SCORE:String                  = "score";
		protected static const		JSON_PROPERTY_ROLE:String                   = "role";
		protected static const		JSON_PROPERTY_LINEUP:String                 = "lineup";
		protected static const		JSON_PROPERTY_CARDS:String                 	= "hand";
		protected static const		JSON_PROPERTY_ROUND_INFO:String             = "roundInfo";
		protected static const		JSON_PROPERTY_GK:String                     = "gk";
		protected static const		JSON_PROPERTY_D1:String                     = "d1";
		protected static const		JSON_PROPERTY_D2:String                     = "d2";
		protected static const		JSON_PROPERTY_MF:String                     = "mf";
		protected static const		JSON_PROPERTY_F1:String                     = "f1";
		protected static const		JSON_PROPERTY_F2:String                     = "f2";
		protected static const		JSON_PROPERTY_ROUNDTIME:String				= "roundTime";
		protected static const		JSON_PROPERTY_FORMATION:String				= "formation";
		
		// Events
		public static const     	EVENT_GAME_TEAM_CHANGED:String				= "game_team_changed";
		
		// -------------------------------------------------------------------------------
		// FIELDS
		// -------------------------------------------------------------------------------
		
		private var _name:String;
		private var _score:uint;
		private var	_role:GameRole;
		private var	_formation:GameFormation;
		private var	_cards:GameCards;
		private var	_roundTime:Date;
		private var	_isPlayerTeam:Boolean;
		private var	_game:Game; // Game reference
		
		// -------------------------------------------------------------------------------
		// CONSTRUCTOR
		// -------------------------------------------------------------------------------
		
		public function GameTeam(game:Game, data:Object = null)
		{
			// Ancestor constructor
			super();
			// Game reference
			_game = game;
			// Init
			_formation = new GameFormation(this);
			_cards = new GameCards(this);
			// Clear data
			clear();
			// If data is provided, initializes the instance
			if (data != null) load(data);
		}
		
		// -------------------------------------------------------------------------------
		// PROPERTIES
		// -------------------------------------------------------------------------------
		
		public function get game():Game
		{
			return _game;
		}
		
		[Bindable(event="game_team_changed")]
		public function get name():String
		{
			return _name;
		}
		
		[Bindable(event="game_team_changed")]
		public function get score():uint
		{
			return _score;
		}
		
		[Bindable(event="game_team_changed")]
		public function get role():GameRole
		{
			return _role;
		}
		
		[Bindable(event="game_team_changed")]
		public function get formation():GameFormation
		{
			return _formation;
		}
		
		[Bindable(event="game_team_changed")]
		public function get cards():GameCards
		{
			return _cards;
		}
		
		[Bindable(event="game_team_changed")]
		public function get roundTime():Date
		{
			return _roundTime;
		}
		
		[Bindable(event="game_team_changed")]
		public function get isAttacking():Boolean
		{
			return _role == GameRole.ATTACK;
		}
		
		[Bindable(event="game_team_changed")]
		public function get isValid():Boolean
		{
			return	_formation.isValid 						&&
					_role		!= GameRole.IDLE			&&
					_roundTime	!= DateUtils.INVALID_DATE	&&
					!StringUtils.isEmpty(_name);
		}
		
		public function get isPlayerTeam():Boolean
		{
			return _isPlayerTeam;
		}
		
		// -------------------------------------------------------------------------------
		// PRIVATE METHODS
		// -------------------------------------------------------------------------------
		
		// Utilities
		
		internal function setIsPlayerTeam(value:Boolean):void
		{
			_isPlayerTeam = value;
		}
		
		// DataObject implementation
		
		override protected function validate(data:Object):void
		{
			if (!data.hasOwnProperty(JSON_PROPERTY_NAME)) 		throwLoadMissingPropError(JSON_PROPERTY_NAME);
			if (!data.hasOwnProperty(JSON_PROPERTY_SCORE)) 		throwLoadMissingPropError(JSON_PROPERTY_SCORE);
			if (!data.hasOwnProperty(JSON_PROPERTY_ROLE)) 		throwLoadMissingPropError(JSON_PROPERTY_ROLE);
			if (!data.hasOwnProperty(JSON_PROPERTY_LINEUP)) 	throwLoadMissingPropError(JSON_PROPERTY_LINEUP);
			if (!data.hasOwnProperty(JSON_PROPERTY_CARDS))		throwLoadMissingPropError(JSON_PROPERTY_CARDS);
			if (!data.hasOwnProperty(JSON_PROPERTY_ROUND_INFO))	throwLoadMissingPropError(JSON_PROPERTY_ROUND_INFO);
		}
		
		override protected function adapt(data:Object):Object
		{
			// Output
			var output:Object = new Object();
			// Raw data shortcut
			var raw_players:Array = data[JSON_PROPERTY_LINEUP];
			var raw_info:Object = data[JSON_PROPERTY_ROUND_INFO];
			// Roundtime
			var roundtime:String = "";
			// Players dictionary
			var formation:Dictionary = new Dictionary(true);
			// Loops over all the properties in the 'roundInfo' struct
			for (var prop:Object in raw_info)
			{
				// Search for 'roundTime' option
				if (prop == JSON_PROPERTY_ROUNDTIME)
				{
					roundtime = raw_info[JSON_PROPERTY_ROUNDTIME];
				}
				else
				{
					// Retrieve the id of the card
					var instanceId:String = raw_info[prop];
					// Search the right object into the player lineup
					for (var i:int = 0; i < raw_players.length; i++)
					{
						if (raw_players[i].instanceId == instanceId)
						{
							formation[prop] = raw_players[i];
							break;
						}
					}
				}
			}
			// Produce the output object
			if (data.hasOwnProperty(JSON_PROPERTY_NAME))	output[JSON_PROPERTY_NAME]	= data[JSON_PROPERTY_NAME];
			if (data.hasOwnProperty(JSON_PROPERTY_SCORE))	output[JSON_PROPERTY_SCORE]	= data[JSON_PROPERTY_SCORE];
			if (data.hasOwnProperty(JSON_PROPERTY_ROLE))	output[JSON_PROPERTY_ROLE]	= data[JSON_PROPERTY_ROLE];
			if (data.hasOwnProperty(JSON_PROPERTY_CARDS))	output[JSON_PROPERTY_CARDS]	= data[JSON_PROPERTY_CARDS];
			output[GameTeam.JSON_PROPERTY_ROUNDTIME] = roundtime;
			output[GameTeam.JSON_PROPERTY_FORMATION] = formation;
			// Returns the adapted object
			return output;
		}
		
		override protected function fill(data:Object):void
		{
			if (data.hasOwnProperty(JSON_PROPERTY_NAME))		_name 		= data[JSON_PROPERTY_NAME];
			if (data.hasOwnProperty(JSON_PROPERTY_SCORE))		_score		= data[JSON_PROPERTY_SCORE];
			if (data.hasOwnProperty(JSON_PROPERTY_ROLE))		_role		= GameRole.getBySign(data[JSON_PROPERTY_ROLE]);
			// if (data.hasOwnProperty(JSON_PROPERTY_ROUNDTIME))	_roundTime	= DateUtils.parse(data[JSON_PROPERTY_ROUNDTIME]); // Patch per il parsing delle date
			if (data.hasOwnProperty(JSON_PROPERTY_ROUNDTIME))	_roundTime	= DateUtils.parse(data[JSON_PROPERTY_ROUNDTIME].toString().replace(/-/g, "/")); // Patch per il parsing delle date
			if (data.hasOwnProperty(JSON_PROPERTY_CARDS))		_cards.load(data[JSON_PROPERTY_CARDS]);
			if (data.hasOwnProperty(JSON_PROPERTY_FORMATION))	_formation.load(data[JSON_PROPERTY_FORMATION]);
			// Dispatch event EVENT_GAME_TEAM_CHANGED
			dispatchGameTeamChanged();
		}

		
		// Events dispatcher
		
		protected function dispatchGameTeamChanged():void
		{
			dispatchEvent(new Event(EVENT_GAME_TEAM_CHANGED));
		}
		
		// -------------------------------------------------------------------------------
		// PUBLIC METHODS
		// -------------------------------------------------------------------------------
		
		public function getPlayer(position:Position):GamePlayerCard
		{
			return _formation.getPlayer(position);
		}
		
		public function getPlayerPosition(player:GamePlayerCard):Position
		{
			return _formation.getPlayerPosition(player);
		}
		
		public function equals(gameTeam:GameTeam):Boolean
		{
			return	_name 	== 	gameTeam.name		&&
					_score	==	gameTeam.score		&&
					_role	==	gameTeam.role		&&
					_formation.equals(gameTeam.formation)	&&
					_cards.equals(gameTeam.cards);
		}
		
		override public function clear():void
		{
			// Clears data
			_name		= "";
			_score		= 0;
			_role		= GameRole.IDLE;
			_roundTime	= DateUtils.INVALID_DATE;
			// Clears objects
			_formation.clear();
			_cards.clear();
		}
	
	}

}